package event

import (
	"fmt"
	"net"
	"sync"
)

type Server struct {
	Host        string
	Port        int
	Listener    *net.TCPListener
	Conn        *net.TCPConn
	IsRunning   bool
	ClientCount uint32
	Clients     map[uint32]net.Conn
	Mutex       sync.Mutex
	EventBus    *EventBus
}

func NewServer() *Server {
	eb := new(EventBus)
	eb.Bus = make(map[string][]EventHandler)
	return &Server{
		Host:      "0.0.0.0",
		Port:      DEFAULT_SERVER_PORT,
		IsRunning: false,
		Clients:   make(map[uint32]net.Conn),
		Mutex:     sync.Mutex{},
		EventBus:  eb,
	}
}

func (s *Server) Start() {
	addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", s.Host, s.Port))
	if err != nil {
		panic(err)
	}
	s.Listener, err = net.ListenTCP("tcp", addr)
	if err != nil {
		panic(err)
	}
	s.IsRunning = true
	go s.Listen()
	println("server start")
}

func (s *Server) Send(data []byte, conn net.Conn) {
	println("server send:", conn, fmt.Sprintf("%v", data))
	s.Mutex.Lock()
	defer s.Mutex.Unlock()
	_, err := (conn).Write(data)
	if err != nil {
		println("sever send error", err.Error())
		println("server send:", conn, fmt.Sprintf("%v", data))
	} else {
		println("send success")
	}
}

func (s *Server) Close() {
	s.IsRunning = false
	s.Conn.Close()
}

func (s *Server) Listen() {
	for s.IsRunning {
		conn, err := s.Listener.Accept()
		if err != nil {
			println("server listen error", err.Error())
			continue
		}
		go s.handle(conn)
	}
	println("event message server stop")
}

func (s *Server) handle(conn net.Conn) {
	defer conn.Close()
	for s.IsRunning {
		data := make([]byte, 1024)
		n, err := conn.Read(data)
		if err != nil {
			if err.Error() == "EOF" {
				s.HandleUnReg(conn)
				return
			}
			println("server handle read error", err.Error())
			// time.Sleep(1 * time.Second)
			return
		}
		data = data[:n]
		if !isValidMessage(data) {
			return
		}
		switch data[8] {
		case MessageTypeRegister:
			s.HandleReg(conn)
		case MessageTypeUnRegister:
			s.HandleUnReg(conn)
		case MessageTypePing:
			s.Pong(data, conn)
		case MessageTypeEventReg:
			s.HandleEventReg(data, conn)
		case MessageTypeEvent:
			s.HandleEventMessage(data, conn)
		}
	}
	println("server stop hanlde")
}

func (s *Server) Pong(message []byte, conn net.Conn) {
	clientId := [4]byte{0, 0, 0, 0}
	if message[2] == 0 && message[3] == 0 && message[4] == 0 && message[5] == 0 {
		clientId = s.HandleReg(conn)
	}
	pongMessage := NewPongMessage(clientId)
	s.Send(pongMessage[:], conn)
}

func (s *Server) HandleReg(conn net.Conn) [4]byte {
	s.Mutex.Lock()
	s.Clients[s.ClientCount] = conn
	//int64 转 []byte
	id := [4]byte{}
	id[0] = byte(s.ClientCount >> 24)
	id[1] = byte(s.ClientCount >> 16)
	id[2] = byte(s.ClientCount >> 8)
	id[3] = byte(s.ClientCount)
	message := NewRegMessage(id)
	s.Mutex.Unlock()
	s.Send(message[:], conn)
	s.ClientCount++
	return id
}

func (s *Server) HandleUnReg(conn net.Conn) {
	s.Mutex.Lock()
	defer s.Mutex.Unlock()
	for k, v := range s.Clients {
		if v == conn {
			delete(s.Clients, k)
			break
		}
	}
}

func (s *Server) HandleEventReg(message []byte, conn net.Conn) {
	eventMessage := new(EventMessage)
	eventMessage.FromBytes(message[32:])
	s.EventBus.Subscribe(eventMessage.Topic, func(data interface{}) {
		println("conn", conn)
		if orignMessage, ok := data.([]byte); ok {
			s.Send(orignMessage, conn)
		}
	})
}
func (s *Server) HandleEventMessage(message []byte, conn net.Conn) {
	eventMessage := new(EventMessage)
	eventMessage.FromBytes(message[32:])
	s.EventBus.Publish(eventMessage.Topic, message)
}
